package com.zeus.monitor.metrics;

import com.zeus.monitor.annotation.ZeusCounter;
import com.zeus.monitor.annotation.ZeusTimer;
import io.prometheus.client.Counter;
import io.prometheus.client.Summary;
import org.springframework.beans.factory.annotation.Value;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author magic
 * @date 2018/11/8/008 16:40
 * @version 1.0
 * Description ZeusMetrics
 */
public class ZeusMetrics {

    private static Map<String, Counter> counterMap = new ConcurrentHashMap<>(16);

    private static Map<String, Summary> timerMap = new ConcurrentHashMap<>(16);

    private static final String COUNTER_STATUS = "status";

    private ReentrantLock reentrantCounterLock = new ReentrantLock();
    private ReentrantLock reentrantSummaryLock = new ReentrantLock();


    @Value("${spring.application.name:undefined_application_name}")
    private String applicationName;

    private String buildName(String name){
        final String appName = applicationName.replaceAll("-","_");
        StringBuilder builder = new StringBuilder(appName);
        builder.append("_")
                .append(name);
        return builder.toString();
    }

    public Counter getOrInitCounter(ZeusCounter counter) {
        final String builderName = buildName(counter.name());
        if(counterMap.containsKey(builderName)){
           return counterMap.get(builderName);
        }
       try {
           reentrantCounterLock.lock();
           if(counterMap.containsKey(builderName)){
               return counterMap.get(builderName);
           }
           Counter prometheusCounter = Counter.build()
                   .name(builderName)
                   .labelNames(COUNTER_STATUS)
                   .help(counter.desc())
                   .register();
           counterMap.put(builderName,prometheusCounter);
           return prometheusCounter;
       }finally {
           reentrantCounterLock.unlock();
       }
    }

    public Summary getOrInitTimer(ZeusTimer zeusTimer) {
        final String builderName = buildName(zeusTimer.name());
        if(timerMap.containsKey(builderName)){
            return timerMap.get(builderName);
        }
        try {
            reentrantSummaryLock.lock();
            if(timerMap.containsKey(builderName)){
                return timerMap.get(builderName);
            }
            Summary summary = Summary.build()
                    .name(builderName)
                    .help(zeusTimer.desc())
                    .register();
            timerMap.put(builderName,summary);
            return summary;
        }finally {
            reentrantSummaryLock.unlock();
        }
    }
}
